﻿using System.Windows.Data;
using DimensionsHelper.Common.Contracts;
using DimensionsHelper.Common.Contracts.Services;

namespace DimensionsHelper.Client.ViewModels.TaskPanel;

public class TaskListViewModel : ObservableCollection<TaskViewModel>, IRecipient<IRunnable>
{
    private static readonly object Lock = new();

    private readonly IServiceProvider _serviceProvider;
    private readonly HashSet<string> _taskNameSet = [];


    private TaskViewModel? _lastTask;


    public TaskListViewModel(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
        WeakReferenceMessenger.Default.Register(this);
        BindingOperations.EnableCollectionSynchronization(this, Lock);
    }


    public TaskViewModel? LastTask
    {
        get => _lastTask;

        set
        {
            if (_lastTask == value)
            {
                return;
            }

            _lastTask = value;
            OnPropertyChanged(new PropertyChangedEventArgs(nameof(LastTask)));
        }
    }


    public void Receive(IRunnable message)
    {
        // 查找同类型且没有正在运行的任务
        TaskViewModel? task = this.FirstOrDefault(t => t.Section.Equals(message.Section) && !t.IsTaskRunning);

        if (task == null)
        {
            string name = GetTaskName(message);
            _taskNameSet.Add(name);
            task = _serviceProvider.GetRequiredService<TaskViewModel>();
            task.TaskId = name;
            task.RemoveSelf += OnTaskRemoveSelf;

            if (message is IProjectService projectService)
            {
                projectService.ReportService = task;
            }

            Add(task);
        }

        task.StartTask(message.Run);
        LastTask = task;
    }


    public void RegisterLastTaskChangedHandler(Action<TaskViewModel?> callback)
    {
        PropertyChanged -= OnLastTaskChanged;
        PropertyChanged += OnLastTaskChanged;

        return;

        void OnLastTaskChanged(object? sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != nameof(LastTask))
            {
                return;
            }

            callback(LastTask);
        }
    }


    private void OnTaskRemoveSelf(TaskViewModel task)
    {
        if (task.IsTaskRunning)
        {
            task.Cancel();
        }

        Remove(task);
        _taskNameSet.Remove(task.TaskId);
    }


    private string GetTaskName(IRunnable runnable)
    {
        int count = 0;
        string taskName = runnable.Section;

        while (_taskNameSet.Contains(taskName))
        {
            count++;
            taskName = $@"{runnable.Section}`{count}";
        }

        return taskName;
    }
}